<!DOCTYPE html>
<html lang="zh-Hans">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222"><meta name="generator" content="Hexo 6.2.0">


  <link rel="apple-touch-icon" sizes="180x180" href="/vhuichen.ico">
  <link rel="icon" type="image/png" sizes="32x32" href="/vhuichen.ico">
  <link rel="icon" type="image/png" sizes="16x16" href="/vhuichen.ico">
  <link rel="mask-icon" href="/vhuichen.ico" color="#222">

<link rel="stylesheet" href="/css/main.css">



<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css" integrity="sha256-AbA177XfpSnFEvgpYu1jMygiLabzPCJCRIBtR5jGc0k=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.1/animate.min.css" integrity="sha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE=" crossorigin="anonymous">

<script class="next-config" data-name="main" type="application/json">{"hostname":"vhuichen.github.io","root":"/","images":"/images","scheme":"Pisces","darkmode":false,"version":"8.13.0","exturl":false,"sidebar":{"position":"left","display":"display","padding":18,"offset":12},"copycode":{"enable":false,"style":null},"bookmark":{"enable":false,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"stickytabs":false,"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"Searching...","empty":"We didn't find any results for the search: ${query}","hits_time":"${hits} results found in ${time} ms","hits":"${hits} results found"}}</script><script src="/js/config.js"></script>

    <meta property="og:type" content="website">
<meta property="og:title" content="vhuichen">
<meta property="og:url" content="https://vhuichen.github.io/page/2/index.html">
<meta property="og:site_name" content="vhuichen">
<meta property="og:locale">
<meta property="article:author" content="vhuichen">
<meta name="twitter:card" content="summary">


<link rel="canonical" href="https://vhuichen.github.io/page/2/">



<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":true,"isPost":false,"lang":"zh-Hans","comments":"","permalink":"","path":"page/2/index.html","title":""}</script>

<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>vhuichen</title>
  






  <noscript>
    <link rel="stylesheet" href="/css/noscript.css">
  </noscript>
</head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="Toggle navigation bar" role="button">
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <i class="logo-line"></i>
      <h1 class="site-title">vhuichen</h1>
      <i class="logo-line"></i>
    </a>
      <p class="site-subtitle" itemprop="description">记录、分享</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>



<nav class="site-nav">
  <ul class="main-menu menu"><li class="menu-item menu-item-home"><a href="/" rel="section">Home</a></li><li class="menu-item menu-item-archives"><a href="/archives/" rel="section">Archives</a></li><li class="menu-item menu-item-about"><a href="/about/" rel="section">About</a></li>
  </ul>
</nav>




</div>
        
  
  <div class="toggle sidebar-toggle" role="button">
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
  </div>

  <aside class="sidebar">

    <div class="sidebar-inner sidebar-overview-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          Table of Contents
        </li>
        <li class="sidebar-nav-overview">
          Overview
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author site-overview-item animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="vhuichen"
      src="/images/vhuichen.jpg">
  <p class="site-author-name" itemprop="name">vhuichen</p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap site-overview-item animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
        <a href="/archives/">
          <span class="site-state-item-count">78</span>
          <span class="site-state-item-name">posts</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
          <a href="/categories/">
        <span class="site-state-item-count">11</span>
        <span class="site-state-item-name">categories</span></a>
      </div>
      <div class="site-state-item site-state-tags">
          <a href="/tags/">
        <span class="site-state-item-count">86</span>
        <span class="site-state-item-name">tags</span></a>
      </div>
  </nav>
</div>



        </div>
      </div>
    </div>
  </aside>
  <div class="sidebar-dimmer"></div>


    </header>

    
  <div class="back-to-top" role="button" aria-label="Back to top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


    <div class="main-inner index posts-expand">

    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="https://vhuichen.github.io/2021/04/NetworkProtocol/HTTP%E5%8D%8F%E8%AE%AE/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/vhuichen.jpg">
      <meta itemprop="name" content="vhuichen">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="vhuichen">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
      <meta itemprop="name" content="undefined | vhuichen">
      <meta itemprop="description" content="">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/04/NetworkProtocol/HTTP%E5%8D%8F%E8%AE%AE/" class="post-title-link" itemprop="url">HTTP协议</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Posted on</span>

      <time title="Created: 2021-04-15 00:00:00" itemprop="dateCreated datePublished" datetime="2021-04-15T00:00:00+08:00">2021-04-15</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar-check"></i>
      </span>
      <span class="post-meta-item-text">Edited on</span>
      <time title="Modified: 2021-07-14 23:24:17" itemprop="dateModified" datetime="2021-07-14T23:24:17+08:00">2021-07-14</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">In</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E7%BD%91%E7%BB%9C%E5%8D%8F%E8%AE%AE/" itemprop="url" rel="index"><span itemprop="name">网络协议</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h2 id="HTTP"><a href="#HTTP" class="headerlink" title="HTTP"></a>HTTP</h2><p>HTTP 即超文本传输协议（HyperText Transfer Protocol）</p>
<h3 id="HTTP-连接流程"><a href="#HTTP-连接流程" class="headerlink" title="HTTP 连接流程"></a>HTTP 连接流程</h3><p><img src="https://gitee.com/vhuichen/images/raw/master/img/20210418175541.jpg"></p>
<ul>
<li>域名解析  </li>
<li>发起TCP的3次握手   </li>
<li>Web浏览器向Web服务器发送http请求命令  </li>
<li>Web浏览器发送http请求头信息</li>
<li>Web服务器应答  </li>
<li>Web服务器发送应答头信息   </li>
<li>Web服务器向浏览器发送数据    </li>
<li>Web服务器关闭TCP连接</li>
</ul>
<p>TCP连接在发送后将仍然保持打开状态，浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间，还节约了网络带宽。</p>
<h4 id="HTTP存在的问题"><a href="#HTTP存在的问题" class="headerlink" title="HTTP存在的问题"></a>HTTP存在的问题</h4><ul>
<li><p>窃听风险<br><img src="https://gitee.com/vhuichen/images/raw/master/img/20210418175539.jpg"></p>
</li>
<li><p>篡改风险<br><img src="https://gitee.com/vhuichen/images/raw/master/img/20210418175538.jpg"></p>
</li>
<li><p>冒充风险<br><img src="https://gitee.com/vhuichen/images/raw/master/img/20210418175543.jpg"></p>
</li>
</ul>
<h4 id="HTTP各版本区别"><a href="#HTTP各版本区别" class="headerlink" title="HTTP各版本区别"></a>HTTP各版本区别</h4><p>HTTP1.x 版本数据传输是通过多个TCP实现的，同时最多开启的TCP可以达到6~8个</p>
<h3 id="1-0"><a href="#1-0" class="headerlink" title="1.0"></a>1.0</h3><ul>
<li>无法长连接，请求完数据立即断开TCP</li>
</ul>
<h3 id="1-1"><a href="#1-1" class="headerlink" title="1.1"></a>1.1</h3><ul>
<li>引入了长连接，TCP可以被多个请求复用   </li>
<li>引入了管道机制，同一个TCP里面可以发送多个请求，但服务器还是顺序执行，可能会出现“队头阻塞”<br><img src="https://gitee.com/vhuichen/images/raw/master/img/20210418175506.jpg"></li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">HTTP1.1 遗留问题：  </span><br><span class="line">1、头部没有压缩就发送，数据量大。多个请求的头部是一样的</span><br><span class="line">2、服务器是按照请求的顺序响应的，会出现“队头阻塞”  </span><br><span class="line">3、没有请求优先级控制  </span><br><span class="line">4、服务器无法主动下发数据  </span><br></pre></td></tr></table></figure>

<h3 id="2-0"><a href="#2-0" class="headerlink" title="2.0"></a>2.0</h3><ul>
<li>二进制格式<br>头信息和数据体都是二进制，并且统称为帧(frame)：头信息帧和数据帧。</li>
<li>数据流<br>每个数据流都标记着一个独一无二的编号，其中规定客户端发出的数据流编号为奇数， 服务器发出的数据流编号为偶数。 </li>
<li>优先级<br>客户端还可以指定数据流的优先级。优先级高的请求，服务器就先响应该请求。</li>
<li>多路复用<br>一个连接中并发多个请求或回应，而不用按照顺序一一对应。</li>
<li>头部压缩<br>同时发出多个请求，他们的头是一样的或是相似的，那么，协议会帮你消除重复的部分。</li>
<li>服务器推送<br>请求 HTML 的时候，就提前把可能会用到的 JS、CSS 文件等静态资源主动发给客户端，减少延时的等待</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">遗留问题：</span><br><span class="line">1.x 是通过多个TCP传输数据的，2.0 改为单个TCP传输数据，当一个TCP丢包需要重发时，会阻塞HTTP请求</span><br></pre></td></tr></table></figure>

<h3 id="3-0"><a href="#3-0" class="headerlink" title="3.0"></a>3.0</h3><ul>
<li>将 TCP 改为 UDP</li>
</ul>
<h2 id="HTTPS"><a href="#HTTPS" class="headerlink" title="HTTPS"></a>HTTPS</h2><p>HTTPS &#x3D; HTTP + SSL&#x2F;TLS</p>
<h4 id="改善"><a href="#改善" class="headerlink" title="改善"></a>改善</h4><ul>
<li>信息加密<br>混合加密的方式实现信息的机密性，解决了窃听的风险。</li>
<li>校验机制<br>摘要算法的方式来实现完整性，它能够为数据生成独一无二的「指纹」，指纹用于校验数据的完整性，解决了篡改的风险。</li>
<li>身份证书<br>将服务器公钥放入到数字证书中，解决了冒充的风险。</li>
</ul>
<h3 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h3><p>HTTS 采用混合加密方式（非对称加密 + 对称加密），建立连接时使用非对称加密，建立连接后使用对称加密。</p>
<h4 id="非对称加密"><a href="#非对称加密" class="headerlink" title="非对称加密"></a>非对称加密</h4><p>拥有两个密钥，公钥和私钥。公钥加密，私钥解密，反过来，私钥加密，公钥解密。<br>特性：加解密慢（使用了大量的乘除法）。适用于一对多通信。安全性高，私钥是保密的。</p>
<h4 id="对称加密"><a href="#对称加密" class="headerlink" title="对称加密"></a>对称加密</h4><p>加密和解密使用同一个秘钥<br>特性：加解密快（只使用了位移操作）。适用于一对一通信。秘钥难分发，难管理。</p>
<h4 id="数字摘要（摘要算法、哈希算法、散列算法）"><a href="#数字摘要（摘要算法、哈希算法、散列算法）" class="headerlink" title="数字摘要（摘要算法、哈希算法、散列算法）"></a>数字摘要（摘要算法、哈希算法、散列算法）</h4><p>采用单向Hash函数生成一个不可逆的“摘要”。<br>常用的数字摘要算法：MD5、SHA-1、SHA-2<br>特点：单向，不可逆  </p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">数字摘要保证了数据的唯一性，相同的文本得到的“摘要”一定相等，不相等的文本得到的“摘要”极小概率相等（哈希碰撞）</span><br></pre></td></tr></table></figure>

<h4 id="数字签名"><a href="#数字签名" class="headerlink" title="数字签名"></a>数字签名</h4><p>对 <code>明文 + 数字摘要</code> 进行加密，得到的就是<code>数字签名</code></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">数字签名保证了数据的完整性</span><br></pre></td></tr></table></figure>
<p><img src="https://gitee.com/vhuichen/images/raw/master/img/20210418175545.jpg"></p>
<h4 id="数字证书"><a href="#数字证书" class="headerlink" title="数字证书"></a>数字证书</h4><p><code>数字签名</code>用CA（权威的认证机构）的私钥加密，得到<code>数字证书</code>   </p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">数字证书保证和数据的安全性</span><br></pre></td></tr></table></figure>
<h4 id="证书认证流程"><a href="#证书认证流程" class="headerlink" title="证书认证流程"></a>证书认证流程</h4><p><img src="https://gitee.com/vhuichen/images/raw/master/img/20210419012708.jpg"></p>
<h4 id="证书解析流程"><a href="#证书解析流程" class="headerlink" title="证书解析流程"></a>证书解析流程</h4><p><img src="https://gitee.com/vhuichen/images/raw/master/img/20210418175540.jpg"></p>
<h4 id="连接流程"><a href="#连接流程" class="headerlink" title="连接流程"></a>连接流程</h4><p><img src="https://gitee.com/vhuichen/images/raw/master/img/20210418175542.jpg"></p>
<h3 id="参考文章"><a href="#参考文章" class="headerlink" title="参考文章"></a>参考文章</h3><p><a target="_blank" rel="noopener" href="https://www.toutiao.com/a6802216564595622408">https://www.toutiao.com/a6802216564595622408</a></p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="https://vhuichen.github.io/2021/04/NetworkProtocol/TCP%E5%8D%8F%E8%AE%AE/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/vhuichen.jpg">
      <meta itemprop="name" content="vhuichen">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="vhuichen">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
      <meta itemprop="name" content="undefined | vhuichen">
      <meta itemprop="description" content="">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/04/NetworkProtocol/TCP%E5%8D%8F%E8%AE%AE/" class="post-title-link" itemprop="url">TCP协议</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Posted on</span>

      <time title="Created: 2021-04-15 00:00:00" itemprop="dateCreated datePublished" datetime="2021-04-15T00:00:00+08:00">2021-04-15</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar-check"></i>
      </span>
      <span class="post-meta-item-text">Edited on</span>
      <time title="Modified: 2021-07-14 23:24:29" itemprop="dateModified" datetime="2021-07-14T23:24:29+08:00">2021-07-14</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">In</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E7%BD%91%E7%BB%9C%E5%8D%8F%E8%AE%AE/" itemprop="url" rel="index"><span itemprop="name">网络协议</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h1 id="TCP"><a href="#TCP" class="headerlink" title="TCP"></a>TCP</h1><p>TCP 全称传输控制协议（Transmission Control Protocol），是面向连接的、可靠的、基于字节流的传输层通信协议</p>
<h2 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h2><h3 id="停止等待协议"><a href="#停止等待协议" class="headerlink" title="停止等待协议"></a>停止等待协议</h3><p>A 每发一个包给 B，都必须收到 B 的确认（ACK） ，在规定的时间内 A 没有收到 ACK 包，则重传。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">停止等待协议有一个问题，如果 B 收到了 A 的包，但是返回的 ACK 包丢失了，此时依然会触发 A 重传</span><br></pre></td></tr></table></figure>
<h3 id="累计确认-累计应答"><a href="#累计确认-累计应答" class="headerlink" title="累计确认(累计应答)"></a>累计确认(累计应答)</h3><p>A同时发送5个数据包，并给这5个数据包序号（seq）（1，2，3，4，5），B再收到数据包后再返回的 ACK 包中返回确认号(ack)，表示当前未收到的最小编号。通过这种方式就可以处理<code>停止等待协议</code>带来的问题。  </p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">如果B顺序收到1，2，3，4，5编号的包，那么返回的ack号分别为2，3，4，5，6  </span><br><span class="line">如果B顺序收到3，5，1，4，2编号的包，那么返回的ack号分别为1，1，2，2，6</span><br><span class="line"></span><br><span class="line">假如3数据包发送时丢包了</span><br><span class="line">如果B顺序收到1，2，4，5编号的包，那么返回的ack号分别为2，3，3，3  </span><br><span class="line">如果B顺序收到4，5，1，2编号的包，那么返回的ack号分别为1，1，2，3</span><br></pre></td></tr></table></figure>

<h3 id="流量控制"><a href="#流量控制" class="headerlink" title="流量控制"></a>流量控制</h3><p>每个计算机处理能力不一样，如果发送太快，接受太慢怎么办？<br>A、B 在每个数据包中加上一个值，叫<code>窗口大小</code>（win)，表示接收能力<br><img src="https://gitee.com/vhuichen/images/raw/master/img/20210418233036.png"></p>
<h3 id="拥塞控制"><a href="#拥塞控制" class="headerlink" title="拥塞控制"></a>拥塞控制</h3><p>网络很差时，造成了<code>网络拥塞</code>，假设拥塞窗口的大小为cwnd，流量控制的滑动窗口的大小为rwnd，<br>那么窗口大小 &#x3D; min(cwnd, rwnd)。  </p>
<h3 id="慢启动"><a href="#慢启动" class="headerlink" title="慢启动"></a>慢启动</h3><p>如何知道拥塞窗口的大小呢？可以采用试探法，先发窗口大小为1的包，如果不丢包，就发送窗口为2、4、8的包，直到出现丢包，从而得到最终的拥塞窗口。</p>
<h4 id="滑动窗口"><a href="#滑动窗口" class="headerlink" title="滑动窗口"></a>滑动窗口</h4><p>发送一个数据包过去，不需要等待数据包回来再发送<br><img src="https://gitee.com/vhuichen/images/raw/master/img/20210418205038.jpg"></p>
<h3 id="拥塞机制"><a href="#拥塞机制" class="headerlink" title="拥塞机制"></a>拥塞机制</h3><p>一旦出现丢包，就会触发拥塞机制（慢启动、拥塞规避、快速启动、快速恢复）<br><img src="https://gitee.com/vhuichen/images/raw/master/img/20210419001701.png"></p>
<h2 id="TCP三次握手"><a href="#TCP三次握手" class="headerlink" title="TCP三次握手"></a>TCP三次握手</h2><p><img src="https://gitee.com/vhuichen/images/raw/master/img/20210418175547.jpg"></p>
<ul>
<li>客户端向服务器发出连接请求报文，同部位SYN&#x3D;1，初始序列号seq&#x3D;x，此时客户端进程进入了SYN-SENT（同步已发送状态）状态。</li>
<li>服务器收到请求报文后，发出确认报文，确认报文中 ACK&#x3D;1，SYN&#x3D;1，确认号是ack&#x3D;x+1，同时也要为自己初始化一个序列号 seq&#x3D;y，此时服务器进入了SYN-RCVD（同步收到）状态。</li>
<li>客户端收到报文后，发出确认报文的ACK&#x3D;1，ack&#x3D;y+1，自己的序列号seq&#x3D;x+1，此时，TCP连接建立，客户端进入ESTABLISHED（已建立连接）状态。</li>
<li>当服务器收到客户端的确认后也进入 ESTABLISHED 状态，此后双方就可以开始通信了。</li>
</ul>
<h3 id="为什么是三次"><a href="#为什么是三次" class="headerlink" title="为什么是三次"></a>为什么是三次</h3><p>1、防止已经失效的连接请求报文突然又传送到了服务器，从而产生错误，两次握手会使得客户端和服务端再次建立连接，导致不必要的资源浪费。<br>2、其实也可以说是四次，只是中间两次合并成一次发送了。理由是TCP不允许半连接状态下传输数据。</p>
<h3 id="SYN攻击"><a href="#SYN攻击" class="headerlink" title="SYN攻击"></a>SYN攻击</h3><p>客户端在短时间内伪造了大量的IP进行连接，服务器回复响应包，但是源地址是不存在的，所以服务端会不断的重发，直到重发超时。<br>这些伪造的SYN包将长时间占用未连接队列，影响了正常的SYN，目标系统运行缓慢，严重者引起网络堵塞甚至系统瘫痪。   </p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">部分解决方案：</span><br><span class="line">1、延迟TCB分配方法，缓存半连接状态信息，建立连接后在分配</span><br><span class="line">2、增加最大半连接数</span><br><span class="line">3、缩短超时时间</span><br></pre></td></tr></table></figure>

<h2 id="四次挥手"><a href="#四次挥手" class="headerlink" title="四次挥手"></a>四次挥手</h2><p><img src="https://gitee.com/vhuichen/images/raw/master/img/20210418175544.jpg"></p>
<ul>
<li>客户端发出断开连接报文，并且停止发送数据。FIN&#x3D;1，其序列号为seq&#x3D;u（等于前面已经传送过来的数据的最后一个字节的序号加1），客户端进入FIN-WAIT-1（终止等待1）状态。 </li>
<li>服务器收到连接释放报文，发出确认报文，ACK&#x3D;1，ack&#x3D;u+1，并且带上自己的序列号seq&#x3D;v，服务端就进入了CLOSE-WAIT（关闭等待）状态。这时候处于半关闭状态，即客户端已经没有数据要发送了，但是服务器若发送数据，客户端依然要接受。这个状态还要持续一段时间，也就是整个CLOSE-WAIT状态持续的时间。</li>
<li>客户端收到服务器的确认请求后，此时，客户端就进入FIN-WAIT-2（终止等待2）状态，等待服务器发送连接释放报文（在这之前还需要接受服务器发送的最后的数据）。  </li>
<li>服务器将最后的数据发送完毕后，就向客户端发送连接释放报文，FIN&#x3D;1，ack&#x3D;u+1，由于在半关闭状态，服务器很可能又发送了一些数据，假定此时的序列号为seq&#x3D;w。服务器就进入了LAST-ACK（最后确认）状态，等待客户端的确认。  </li>
<li>客户端收到服务器的连接释放报文后，发出确认，ACK&#x3D;1，ack&#x3D;w+1，而自己的序列号是seq&#x3D;u+1，此时，客户端就进入了TIME-WAIT（时间等待）状态。必须经过2*MSL（最长报文段寿命）的时间后，才进入CLOSED状态。</li>
<li>服务器只要收到了客户端发出的确认，立即进入CLOSED状态。服务器结束TCP连接的时间要比客户端早一些。</li>
</ul>
<h3 id="为什么要-TIME-WAIT，等待2个MSL后才关闭TCP-（2个MSL-Max-Segment-Lifetime，约240秒-）"><a href="#为什么要-TIME-WAIT，等待2个MSL后才关闭TCP-（2个MSL-Max-Segment-Lifetime，约240秒-）" class="headerlink" title="为什么要 TIME_WAIT，等待2个MSL后才关闭TCP （2个MSL(Max Segment Lifetime，约240秒)）"></a>为什么要 TIME_WAIT，等待2个MSL后才关闭TCP （2个MSL(Max Segment Lifetime，约240秒)）</h3><ul>
<li>防止上一次连接中的包，重新出现，影响新连接（经过2MSL，上一次连接中所有的重复包都会消失）  </li>
<li>发送的最后一个ack(fin) ，有可能丢失，这时被动方会重新发fin。</li>
</ul>
<h3 id="为什么是三次握手，四次挥手？关闭一定是四次吗？"><a href="#为什么是三次握手，四次挥手？关闭一定是四次吗？" class="headerlink" title="为什么是三次握手，四次挥手？关闭一定是四次吗？"></a>为什么是三次握手，四次挥手？关闭一定是四次吗？</h3><ul>
<li>连接三次是因为中间两次合并成一次了  </li>
<li>TCP是全双工模式，客户端第一次发送FIN报文，只表示不会再请求数据，但此时服务器还可能需要继续发送数据，等服务器数据发送完，服务器才会发送FIN报文。</li>
<li>如果一端发送FIN报文后，另一端不再需要传输数据，<strong>那么第二次挥手的ACK报文会和第三次挥手的FIN报文合并发送过去</strong>，此时关闭连接只需要三次挥手。</li>
</ul>
<h3 id="客户端突然出现故障怎么处理"><a href="#客户端突然出现故障怎么处理" class="headerlink" title="客户端突然出现故障怎么处理"></a>客户端突然出现故障怎么处理</h3><p>服务器每收到一次客户端的请求后都会重新复位一个计时器，时间通常是设置为2小时，若两小时还没有收到客户端的任何数据，服务器就会发送一个探测报文段，以后每隔75秒发送一次。若一连发送10个探测报文仍然没反应，服务器就认为客户端出了故障，接着就关闭连接。</p>
<h3 id="TCP-报文格式"><a href="#TCP-报文格式" class="headerlink" title="TCP 报文格式"></a>TCP 报文格式</h3><p><img src="https://gitee.com/vhuichen/images/raw/master/img/20210418175546.jpg"></p>
<h2 id="TCP是怎么保证数据可靠性传输的"><a href="#TCP是怎么保证数据可靠性传输的" class="headerlink" title="TCP是怎么保证数据可靠性传输的"></a>TCP是怎么保证数据可靠性传输的</h2><ul>
<li>序列号和确认应答信号</li>
<li>超时重发控制</li>
<li>数据校验</li>
<li>连接管理</li>
</ul>
<h2 id="粘包、拆包"><a href="#粘包、拆包" class="headerlink" title="粘包、拆包"></a>粘包、拆包</h2><p>报文太短，需要合并后发送，报文太长，需要分开发送  </p>
<h4 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h4><ul>
<li>指明数据包长度</li>
<li>结尾加入特殊字符’\n’之类的</li>
</ul>
<h2 id="参考文章"><a href="#参考文章" class="headerlink" title="参考文章"></a>参考文章</h2><p><a target="_blank" rel="noopener" href="https://www.cnblogs.com/xiaolincoding/p/12732052.html">https://www.cnblogs.com/xiaolincoding/p/12732052.html</a><br><a target="_blank" rel="noopener" href="https://www.toutiao.com/i6862639863104012814">https://www.toutiao.com/i6862639863104012814</a><br><a target="_blank" rel="noopener" href="https://www.toutiao.com/i6893802302663033355">https://www.toutiao.com/i6893802302663033355</a><br><a target="_blank" rel="noopener" href="https://mp.weixin.qq.com/s/Uf42QEL6WUSHOwJ403FwOA">https://mp.weixin.qq.com/s/Uf42QEL6WUSHOwJ403FwOA</a></p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="https://vhuichen.github.io/2021/04/iOS/iOS%E6%A3%80%E6%B5%8B%E6%9C%AA%E4%BD%BF%E7%94%A8%E7%9A%84%E7%B1%BB/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/vhuichen.jpg">
      <meta itemprop="name" content="vhuichen">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="vhuichen">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
      <meta itemprop="name" content="undefined | vhuichen">
      <meta itemprop="description" content="">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/04/iOS/iOS%E6%A3%80%E6%B5%8B%E6%9C%AA%E4%BD%BF%E7%94%A8%E7%9A%84%E7%B1%BB/" class="post-title-link" itemprop="url">iOS检测未使用的类</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Posted on</span>

      <time title="Created: 2021-04-13 00:00:00" itemprop="dateCreated datePublished" datetime="2021-04-13T00:00:00+08:00">2021-04-13</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar-check"></i>
      </span>
      <span class="post-meta-item-text">Edited on</span>
      <time title="Modified: 2021-04-26 23:51:56" itemprop="dateModified" datetime="2021-04-26T23:51:56+08:00">2021-04-26</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">In</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/iOS/" itemprop="url" rel="index"><span itemprop="name">iOS</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <p>两种方法<br>1、machO文件中 通过 <code>__objc_classlist</code>  <code>__objc_classrefs</code> 对比<br>2、运行时获取到未使用的类（需要大量测试，或者线上测试）<br>两种方法都不能绝对识别准确，但合并起来准确率很高了，最终再手动确定   </p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br></pre></td><td class="code"><pre><span class="line">#include &lt;dlfcn.h&gt;</span><br><span class="line">#include &lt;mach-o/dyld.h&gt;</span><br><span class="line">#include &lt;mach-o/getsect.h&gt;</span><br><span class="line"></span><br><span class="line">/* 获取 runtime 未使用的类 */</span><br><span class="line">NSMutableSet&lt;NSString *&gt; *runtimeUnusedClass() &#123;</span><br><span class="line">    Dl_info info;</span><br><span class="line">    dladdr((const void *)&amp;runtimeUnusedClass, &amp;info);</span><br><span class="line">    </span><br><span class="line">    const uint64_t mach_header = (uint64_t)info.dli_fbase;</span><br><span class="line">    </span><br><span class="line">    const struct section_64 *classlist = getsectbynamefromheader_64((const struct mach_header_64 *)mach_header, &quot;__DATA&quot;, &quot;__objc_classlist&quot;);</span><br><span class="line">    </span><br><span class="line">    if (classlist) &#123;</span><br><span class="line">        NSMutableSet *classlistUnused = [[NSMutableSet alloc] init];</span><br><span class="line">        // 遍历拿到所有的类</span><br><span class="line">        for (UInt64 addr = classlist-&gt;offset; addr &lt; classlist-&gt;offset + classlist-&gt;size; addr += sizeof(const char **)) &#123;</span><br><span class="line">            uint64_t baseArrr = mach_header + addr;</span><br><span class="line">            </span><br><span class="line">            //获取类对象指针</span><br><span class="line">            uint64_t object_class_addr = *(uint64_t *)(baseArrr);</span><br><span class="line">            //</span><br><span class="line">            uint64_t object_class_isa = *(uint64_t *)(object_class_addr);</span><br><span class="line">            //获取元类对象</span><br><span class="line">            uint64_t object_meta_class_addr;</span><br><span class="line">            if (object_class_isa &amp; (1 &lt;&lt; 0)) &#123;</span><br><span class="line">                object_meta_class_addr = object_class_addr;</span><br><span class="line">            &#125; else &#123;</span><br><span class="line">                object_meta_class_addr = object_class_isa &amp; 0x00007ffffffffff8ULL;</span><br><span class="line">            &#125;</span><br><span class="line">            //偏移32个字节，拿到 class_data_bits 的地址</span><br><span class="line">            uint64_t class_data_bits_addr = object_meta_class_addr + 32;</span><br><span class="line">            //取 class_data_bits 的值</span><br><span class="line">            uint64_t class_data_bits = *(uint64_t *)(class_data_bits_addr);</span><br><span class="line">            //得到 class_rw_t 的指针 (class_rw_t *)(bits &amp; FAST_DATA_MASK);</span><br><span class="line">            uint64_t class_rw_addr = (class_data_bits &amp; 0x00007ffffffffff8UL);</span><br><span class="line">            //取指针的值，得到的第一个数据就是 flags</span><br><span class="line">            uint64_t flags = *(uint64_t *)(class_rw_addr);</span><br><span class="line">            //</span><br><span class="line">            bool isInitialized = flags &amp; (1 &lt;&lt; 29);</span><br><span class="line">            </span><br><span class="line">            if (!isInitialized) &#123;</span><br><span class="line">                //打印类会导致类初始化，所以此方法只能使用一次</span><br><span class="line">                NSString *class = [NSString stringWithFormat:@&quot;%@&quot;, (void *)object_class_addr];</span><br><span class="line">                [classlistUnused addObject:class];</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        return classlistUnused;</span><br><span class="line">    &#125;</span><br><span class="line">    return nil;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/* 获取 MachO 未使用的类 */</span><br><span class="line">NSMutableSet&lt;NSString *&gt; *machOUnusedClass() &#123;</span><br><span class="line">    Dl_info info;</span><br><span class="line">    dladdr((const void *)&amp;machOUnusedClass, &amp;info);</span><br><span class="line">    </span><br><span class="line">    const uint64_t mach_header = (uint64_t)info.dli_fbase;</span><br><span class="line">    </span><br><span class="line">    const struct section_64 *classlist = getsectbynamefromheader_64((const struct mach_header_64 *)mach_header, &quot;__DATA&quot;, &quot;__objc_classlist&quot;);</span><br><span class="line">    const struct section_64 *selfrefs = getsectbynamefromheader_64((const struct mach_header_64 *)mach_header, &quot;__DATA&quot;, &quot;__objc_classrefs&quot;);</span><br><span class="line">    </span><br><span class="line">    if (classlist &amp;&amp; selfrefs) &#123;</span><br><span class="line">        NSMutableSet *classlistSet = [[NSMutableSet alloc] init];</span><br><span class="line">        for (UInt64 addr = classlist-&gt;offset; addr &lt; classlist-&gt;offset + classlist-&gt;size; addr += sizeof(const char **)) &#123;</span><br><span class="line">            uint64_t baseArrr = mach_header + addr;</span><br><span class="line">            Class cls = (__bridge Class)(*(void **)(baseArrr));</span><br><span class="line">            NSString *clsString = [NSString stringWithFormat:@&quot;%@&quot;,cls];</span><br><span class="line">            [classlistSet addObject:clsString];</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        NSMutableSet *selfrefsSet = [[NSMutableSet alloc] init];</span><br><span class="line">        for (UInt64 addr = selfrefs-&gt;offset; addr &lt; selfrefs-&gt;offset + selfrefs-&gt;size; addr += sizeof(const char **)) &#123;</span><br><span class="line">            uint64_t baseArrr = mach_header + addr;</span><br><span class="line">            </span><br><span class="line">            Class cls = (__bridge Class)(*(void **)(baseArrr));</span><br><span class="line">            while (cls) &#123;</span><br><span class="line">                [selfrefsSet addObject:[NSString stringWithFormat:@&quot;%@&quot;,cls]];</span><br><span class="line">                cls = [cls superclass];</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        [classlistSet minusSet:selfrefsSet];</span><br><span class="line">        </span><br><span class="line">        return  classlistSet;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    return nil;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h2 id="缺点"><a href="#缺点" class="headerlink" title="缺点"></a>缺点</h2><p>1、<code>runtimeUnusedClass</code> 方法只有在第一次调用有效，而且必须手动浏览所有的页面（可以考虑放到线上收集）<br>2、两种方法都是不准确的，但未使用的类一定在其中，最终需要手动再次确认。</p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="https://vhuichen.github.io/2021/03/OperatingSystem/%E7%BA%BF%E7%A8%8B&%E8%BF%9B%E7%A8%8B/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/vhuichen.jpg">
      <meta itemprop="name" content="vhuichen">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="vhuichen">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
      <meta itemprop="name" content="undefined | vhuichen">
      <meta itemprop="description" content="">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/03/OperatingSystem/%E7%BA%BF%E7%A8%8B&%E8%BF%9B%E7%A8%8B/" class="post-title-link" itemprop="url">线程&进程</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Posted on</span>

      <time title="Created: 2021-03-28 00:00:00" itemprop="dateCreated datePublished" datetime="2021-03-28T00:00:00+08:00">2021-03-28</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar-check"></i>
      </span>
      <span class="post-meta-item-text">Edited on</span>
      <time title="Modified: 2022-07-24 10:41:15" itemprop="dateModified" datetime="2022-07-24T10:41:15+08:00">2022-07-24</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">In</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/" itemprop="url" rel="index"><span itemprop="name">操作系统</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h3 id="线程-amp-进程"><a href="#线程-amp-进程" class="headerlink" title="线程&amp;进程"></a>线程&amp;进程</h3><h4 id="进程"><a href="#进程" class="headerlink" title="进程"></a>进程</h4><p>程序执行的一个实例，表示一个正在运行的程序，是系统进行资源分配的基本单元，拥有一个完整的虚拟地址空间。</p>
<h4 id="线程"><a href="#线程" class="headerlink" title="线程"></a>线程</h4><p>轻量级进程，程序执行的最小单元，是进程里面的一个实体，线程与资源分配无关，线程自己不拥有资源（只有少量寄存器、栈、线程控制表TCB），线程依赖进程，并与进程内其他线程共享资源。</p>
<h4 id="区别"><a href="#区别" class="headerlink" title="区别"></a>区别</h4><p><code>调度</code>：线程是程序调度、分配的基本单位，而进程拥有资源，各司其职，显著的提高系统的并发运行。同一个进程中，线程切换，进程不需要切换，而进程切换，线程也必须切换。线程切换只需要保存自己的寄存器以及堆栈数据，线程切换还需要分配新的资源。<br><code>并发性</code>：进程之间可以并发，一个进程内的多个线程亦可并发，利用好线程的并发性可以更好地利用资源<br><code>资源</code>：线程只拥有少量资源（寄存器、栈），但可以使用进程的资源<br><code>系统开销</code>：进程切换开销大于线程切换的开销（<code>进程</code>：切换虚拟地址空间、切换CPU上下文、切换内核栈  <code>线程</code>：切换CPU上下文、切换内核栈）<br><code>通信方式</code>：进程间通信需要通过IPC（本身也是一个程序），而线程间通信只是简单的读写数据段。进程资源互不影响，而线程资源则要考虑同步、互斥的问题</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">页表可以将虚拟地址转换为物理内存地址，页表查找很慢，通常使用缓存来加快查找，切换进程，意味着虚拟内存切换、页表切换，从而导致缓存命中率低，查找变慢 </span><br><span class="line"></span><br><span class="line">页表: 类似于字典一个虚拟地址对应一个物理地址，真实机制没搞懂 </span><br><span class="line">虚实地址的映射关系是通过页表来描述的，而mmu正是通过页表来查找虚地址所对应的物理地址。 </span><br></pre></td></tr></table></figure>

<p>进程的上下文切换不仅包含了虚拟内存、栈、全局变量等用户空间的资源，还包括了内核堆栈、寄存器等内核空间的资源。</p>
<h4 id="我自己理解的线程-amp-进程"><a href="#我自己理解的线程-amp-进程" class="headerlink" title="我自己理解的线程&amp;进程"></a>我自己理解的线程&amp;进程</h4><p>进程就是正在执行的程序，线程就是这个程序的最小执行单元，一个进程通常拥有多个线程。进程拥有独立的资源以及虚拟地址空间，而线程只拥有寄存器、栈等少量资源，但进程内部的线程可以共享进程的资源，包括虚拟内存地址。</p>
<h4 id="为什么进程切换比线程切换耗资源"><a href="#为什么进程切换比线程切换耗资源" class="headerlink" title="为什么进程切换比线程切换耗资源"></a>为什么进程切换比线程切换耗资源</h4><ul>
<li>线程切换就是栈、寄存器的切换。  </li>
<li>进程的切换不仅包含了虚拟内存、栈、全局变量等用户空间的资源，还包括了内核堆栈、寄存器等内核空间的资源。</li>
</ul>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="https://vhuichen.github.io/2021/03/NetworkProtocol/%E4%BA%86%E8%A7%A3%20WebSocket/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/vhuichen.jpg">
      <meta itemprop="name" content="vhuichen">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="vhuichen">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
      <meta itemprop="name" content="undefined | vhuichen">
      <meta itemprop="description" content="">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/03/NetworkProtocol/%E4%BA%86%E8%A7%A3%20WebSocket/" class="post-title-link" itemprop="url">了解 WebSocket</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Posted on</span>

      <time title="Created: 2021-03-20 00:00:00" itemprop="dateCreated datePublished" datetime="2021-03-20T00:00:00+08:00">2021-03-20</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar-check"></i>
      </span>
      <span class="post-meta-item-text">Edited on</span>
      <time title="Modified: 2021-07-14 23:24:12" itemprop="dateModified" datetime="2021-07-14T23:24:12+08:00">2021-07-14</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">In</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E7%BD%91%E7%BB%9C%E5%8D%8F%E8%AE%AE/" itemprop="url" rel="index"><span itemprop="name">网络协议</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h2 id="WebSocket"><a href="#WebSocket" class="headerlink" title="WebSocket"></a>WebSocket</h2><p>Websocket 处于应用层协议，他必须依赖 HTTP 协议进行一次握手，握手成功后直接通过单个 TCP 传输数据。<br>Websocket 是为了解决 HTTP 轮询、长轮询的问题</p>
<ul>
<li>轮询：每隔一定时间发出一个请求，耗资源</li>
<li>长轮询：客户端发送一个超长时间的请求，服务器hold住这个请求，直到有新数据时返回</li>
</ul>
<h3 id="WebSocket-amp-Socket"><a href="#WebSocket-amp-Socket" class="headerlink" title="WebSocket &amp; Socket"></a>WebSocket &amp; Socket</h3><p>Socket 本身并不是一个协议。它工作在 OSI 模型会话层（第5层），是为了方便大家直接使用更底层协议（一般是 TCP 或 UDP ）而存在的一个抽象层。Socket是对TCP&#x2F;IP协议的封装，Socket本身并不是协议，而是一个调用接口(API)。<br>Socket 可以指定不同的传输协议（TCP 、UDP）</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">WebSocket 和 Socket 本质没有什么关系。WebSocket 基于 TCP ，Socket 可以基于 TCP、UDP</span><br></pre></td></tr></table></figure>

<h3 id="WebSocket-amp-HTTP"><a href="#WebSocket-amp-HTTP" class="headerlink" title="WebSocket &amp; HTTP"></a>WebSocket &amp; HTTP</h3><ul>
<li>HTTP 是基于<code>请求-应答</code>的方式，WebSocket是双向通信的  </li>
<li>WebSocket 连接使用的是HTTP协议进行连接的，发送了一个标记了 Upgrade 字段的请求，定义了一系列新的header域，标明是 WebSocket 连接。</li>
<li>都是基于TCP的应用层协议。</li>
</ul>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="https://vhuichen.github.io/2021/03/NetworkProtocol/Socket/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/vhuichen.jpg">
      <meta itemprop="name" content="vhuichen">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="vhuichen">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
      <meta itemprop="name" content="undefined | vhuichen">
      <meta itemprop="description" content="">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/03/NetworkProtocol/Socket/" class="post-title-link" itemprop="url">Socket</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Posted on</span>

      <time title="Created: 2021-03-19 00:00:00" itemprop="dateCreated datePublished" datetime="2021-03-19T00:00:00+08:00">2021-03-19</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar-check"></i>
      </span>
      <span class="post-meta-item-text">Edited on</span>
      <time title="Modified: 2021-07-14 23:24:22" itemprop="dateModified" datetime="2021-07-14T23:24:22+08:00">2021-07-14</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">In</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E7%BD%91%E7%BB%9C%E5%8D%8F%E8%AE%AE/" itemprop="url" rel="index"><span itemprop="name">网络协议</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h1 id="Socket"><a href="#Socket" class="headerlink" title="Socket"></a>Socket</h1><p>网络中不同主机上的应用进程之间进行双向通信的端点的抽象。<br>Socket 本身并不是一个协议，而是一个调用接口。它工作在 OSI 模型会话层，是为了方便大家直接使用更底层协议（一般是 TCP 或 UDP ）而存在的一个抽象层。Socket 是对 TCP&#x2F;IP 协议的封装。</p>
<h2 id="Socket-连接流程"><a href="#Socket-连接流程" class="headerlink" title="Socket 连接流程"></a>Socket 连接流程</h2><p>创建 Socket 的时候，可以指定网络层使用的是 IPv4 还是 IPv6，传输层使用的是 TCP 还是 UDP。</p>
<img src="https://gitee.com/vhuichen/images/raw/master/img/20210419122732.png" width="500">

<h3 id="TCP方式-服务器"><a href="#TCP方式-服务器" class="headerlink" title="TCP方式 服务器"></a>TCP方式 服务器</h3><ul>
<li>创建套接字（socket）  </li>
<li>将套接字绑定到一个本地地址和端口上（bind）<br>  当内核收到TCP报文，会通过端口号找到对应的Socket</li>
<li>将套接字设为监听模式，准备接收客户端请求（listen）  </li>
<li>等待客户请求到来，当请求到来后，接收连接请求，返回一个新的对应于此次连接的套接字（accept）<br>  监听 Socket 和真正用来传数据的 Socket 是两个，<code>监听 Socket</code> 以及 <code>已连接 Socket</code></li>
<li>用返回的套接字和客户端进行通信（send&#x2F;recv）  </li>
<li>返回，等待另一客户请求  </li>
<li>关闭套接字</li>
</ul>
<p>在 TCP 连接时，内核为每个 Socket 维护两个队列  </p>
<ul>
<li>TCP 半连接队列，还没完全建立连接的队列</li>
<li>TCP 全连接队列，已经建立连接的队列</li>
</ul>
<h3 id="TCP方式-客户端"><a href="#TCP方式-客户端" class="headerlink" title="TCP方式 客户端"></a>TCP方式 客户端</h3><ul>
<li>创建套接字（socket）  </li>
<li>向服务器发出连接请求（connect）  </li>
<li>和服务器端进行通信（send&#x2F;recv）  </li>
<li>关闭套接字</li>
</ul>
<h3 id="UDP方式-服务器端"><a href="#UDP方式-服务器端" class="headerlink" title="UDP方式 服务器端"></a>UDP方式 服务器端</h3><ul>
<li>创建套接字（socket）  </li>
<li>将套接字绑定到一个本地地址和端口上（bind）  </li>
<li>等待接收数据（recvfrom）  </li>
<li>关闭套接字</li>
</ul>
<h3 id="UDP方式-客户端"><a href="#UDP方式-客户端" class="headerlink" title="UDP方式 客户端"></a>UDP方式 客户端</h3><ul>
<li>创建套接字（socket）  </li>
<li>向服务器发送数据（sendto）  </li>
<li>关闭套接字</li>
</ul>
<h3 id="如何保证-Socket-的长连接"><a href="#如何保证-Socket-的长连接" class="headerlink" title="如何保证 Socket 的长连接"></a>如何保证 Socket 的长连接</h3><p>应用层自己实现心跳包</p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="https://vhuichen.github.io/2021/03/iOS/MVC%E3%80%81MVP%E3%80%81MVVM%E6%A1%86%E6%9E%B6/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/vhuichen.jpg">
      <meta itemprop="name" content="vhuichen">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="vhuichen">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
      <meta itemprop="name" content="undefined | vhuichen">
      <meta itemprop="description" content="">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/03/iOS/MVC%E3%80%81MVP%E3%80%81MVVM%E6%A1%86%E6%9E%B6/" class="post-title-link" itemprop="url">MVC、MVP、MVVM框架</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Posted on</span>

      <time title="Created: 2021-03-14 00:00:00" itemprop="dateCreated datePublished" datetime="2021-03-14T00:00:00+08:00">2021-03-14</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar-check"></i>
      </span>
      <span class="post-meta-item-text">Edited on</span>
      <time title="Modified: 2021-05-09 17:13:43" itemprop="dateModified" datetime="2021-05-09T17:13:43+08:00">2021-05-09</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">In</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/iOS/" itemprop="url" rel="index"><span itemprop="name">iOS</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <!-----
title: MVC、MVP、MVVM框架  
categories:   
- iOS开发  
- 框架   
tags:   
- MVC   
- MVP   
- MVVM   
date: 2021-03-14  

----->



<h2 id="MVC"><a href="#MVC" class="headerlink" title="MVC"></a>MVC</h2><p>苹果的 UIVieController 就是根据 MVC 框架来设计的，UIVieController 持有 View 跟 Model（自己实现），对于一个简单的页面而言在 UIVieController 负责处理业务逻辑，View 负责显示 UI 以及接受用户事件，并将事件传递给 UIVieController，而 Model 负责存储数据。</p>
<h3 id="庞大的-C"><a href="#庞大的-C" class="headerlink" title="庞大的 C"></a>庞大的 C</h3><p>苹果的 MVC 中， C 包含了大量的代码，包括：设置 View 的代码，监听 Model 的代码，网络相关业务逻辑，页面跳转逻辑，这些都是在 C 中实现的。Model 中仅仅包含一些数据，简简单单的一个瘦Model，或者可以将部分数据组装、格式化的逻辑放在 Model 中，让这个 Model 慢慢变成胖Model。<br>而在传统的 MVC 中，Model 是负责网络相关的业务逻辑的，数据通过 Model 提供的接口异步获取，所有跟数据相关的逻辑都应该放在 Model 中。这样做似乎更加合理，但是我在 iOS 开发中却很少见到这样的代码</p>
<h3 id="分离-C-中的代码"><a href="#分离-C-中的代码" class="headerlink" title="分离 C 中的代码"></a>分离 C 中的代码</h3><ol>
<li>设置 View 的代码 可以放在 View 里面（或者 View 分类），事实上我见到的代码很多都是这样做的，甚至不可避免的在 View 中 还会包含一些简单的展示逻辑。此时也可以将监听的代码放在 View 中实现。考虑到苹果原生的 KVO 好多坑，这里可以用 Facebook 的 KVOController 这个库。</li>
<li>网络逻辑本应该放在 Model 中的，但是没放，所以可以将网络逻辑抽出来放在一个单独的文件中，将返回的数据处理好后再交给 Model</li>
<li>分模块，很多 MVC 之所以会“肿”，是因为将 UIVieController 完全当成 C 了，对于一些业务分开的界面，完全可以单独写成一个 MVC 。这样更加合理，也方便修改。对于很复杂的页面，例如包含 UITableView 的页面，就应该将 UITableView 相关的逻辑写成一个 MVC ，每种不同的类型的 UITableViewCell 写成一个 MVC ，最终变成 UITableView（MVC）+ N种类型的 UITableViewCell（MVC）。（PS：实际上项目中这里我都写成 MVC + MVVM 了，不过思想是一样的）</li>
</ol>
<h3 id="优点"><a href="#优点" class="headerlink" title="优点"></a>优点</h3><ol>
<li>简单，很容易上手</li>
<li>相比于其他框架，MVC代码量最少，非常适用于一些业务简单的页面</li>
</ol>
<h3 id="缺点"><a href="#缺点" class="headerlink" title="缺点"></a>缺点</h3><ol>
<li>不太适用于较复杂的页面</li>
<li>业务逻辑都写在 C 中，但 C 和 V 紧密联系在一起，边界缺失，很难对 C 进行单元测试。想象一下，假如现在需要测试 C ，那么 C 的接口在哪里？</li>
</ol>
<h2 id="MVP"><a href="#MVP" class="headerlink" title="MVP"></a>MVP</h2><p>MVP 改进了 MVC，将原来 C 中的业务移到 P 中，V 和 P 通过接口通信 ，感觉好像跟 MVC 没什么区别啊！？？其实是有的<br>最明显的区别就是 MVP 中可以对 P 跟 M  进行单元测试，V 持有 P ，P 持有 M，这样我们很容易模拟 V ， 从而对 P 跟 M 进行单元测试。</p>
<h3 id="优点-1"><a href="#优点-1" class="headerlink" title="优点"></a>优点</h3><ol>
<li>易测试，可以对 P 跟 M  进行单元测试</li>
</ol>
<h3 id="缺点-1"><a href="#缺点-1" class="headerlink" title="缺点"></a>缺点</h3><ol>
<li>V 和 P 之间引入了大量的接口</li>
</ol>
<h2 id="MVVM"><a href="#MVVM" class="headerlink" title="MVVM"></a>MVVM</h2><p>MVVM 改进了 MVP，通过双向绑定机制解决了 MVP 接口很多的问题，MVVM 中的 VM 对应 MVP 的 P，负责处理业务逻辑。通过绑定机制，当 M 发生改变时更新 VM ，VM 发生改变时更新 V ，这些数据更新都不需要通过接口实现。在 iOS 中，这种绑定机制可以用 ReactiveCocoa 或者用 Facebook 的 KVOController + KVC 实现。   </p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">PS：使用 Swift 自身的特性应该可以更好地实现 MVVM，但由于本人目前不太熟悉 Swift ，Demo 中并没有使用 Swift 自身的特性</span><br></pre></td></tr></table></figure>

<h3 id="优点-2"><a href="#优点-2" class="headerlink" title="优点"></a>优点</h3><ol>
<li>易测试，可以对 VM  进行单元测试</li>
<li>双向绑定简化代码</li>
</ol>
<h3 id="缺点-2"><a href="#缺点-2" class="headerlink" title="缺点"></a>缺点</h3><ol>
<li>双向绑定使得查找 bug 变难</li>
</ol>
<h3 id="MVVM-vs-MVC-VM"><a href="#MVVM-vs-MVC-VM" class="headerlink" title="MVVM  vs  MVC-VM"></a>MVVM  vs  MVC-VM</h3><p>在实际开发中不使用绑定机制也可以将数据相关的业务放在 VM 中，这样整个框架看起来就像是 MVC-VM，同样也可以对 VM 进行单元测试。在不使用 ReactiveCocoa 的情况下，这种代码框架在我接触的项目中占比很大，其实很多文章把这种代码框架也叫做 MVVM</p>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><ol>
<li>MVC 简单易上手，但很难进行单元测试（其实，项目开发本来就很少单元测试，甚至没有）</li>
<li>MVP 改进了 MVC ，使得 MVP 很容易进行单元测试，但同时也使得 V 和 P 之间出现一堆交互接口</li>
<li>MVVM 改进了 MVP，使用双向绑定简化了 V 和 P 之间的交互接口</li>
<li>在没有使用 ReactiveCocoa 等框架的情况下，使用没有绑定机制的 MVVM（MVC-VM） 也是个不错的选择</li>
</ol>
<h3 id="Demo"><a href="#Demo" class="headerlink" title="Demo"></a>Demo</h3><p><a target="_blank" rel="noopener" href="https://github.com/vhuichen/Architecture">Demo</a> </p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="https://vhuichen.github.io/2020/08/Swift/%E5%9F%BA%E7%A1%80/Swift%20as%20as!%20as?%20%E7%9A%84%E7%90%86%E8%A7%A3/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/vhuichen.jpg">
      <meta itemprop="name" content="vhuichen">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="vhuichen">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
      <meta itemprop="name" content="undefined | vhuichen">
      <meta itemprop="description" content="">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2020/08/Swift/%E5%9F%BA%E7%A1%80/Swift%20as%20as!%20as?%20%E7%9A%84%E7%90%86%E8%A7%A3/" class="post-title-link" itemprop="url">Swift as as! as? 的理解</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Posted on</span>

      <time title="Created: 2020-08-25 00:00:00" itemprop="dateCreated datePublished" datetime="2020-08-25T00:00:00+08:00">2020-08-25</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar-check"></i>
      </span>
      <span class="post-meta-item-text">Edited on</span>
      <time title="Modified: 2021-07-04 01:19:08" itemprop="dateModified" datetime="2021-07-04T01:19:08+08:00">2021-07-04</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">In</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/Swift/" itemprop="url" rel="index"><span itemprop="name">Swift</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <p>目前公司项目中用到的 Swift 比较少，所以对 Swift 的理解也很局限。这里把一些放在笔记中的内容整理下分享出来。</p>
<h2 id="as"><a href="#as" class="headerlink" title="as"></a>as</h2><p>编译时检测,有两个意思<br>1、指定文字表达类型<br>2、upcast（向上转型，转换成其父类类型）</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//指定 1 的类型为 CGFloat 类型，既变量 num 为 CGFloat 类型</span></span><br><span class="line"><span class="keyword">let</span> num <span class="operator">=</span> <span class="number">1</span> <span class="keyword">as</span> <span class="type">CGFloat</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Animal</span> &#123;&#125;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Dog</span>: <span class="title class_">Animal</span> &#123;&#125;</span><br><span class="line"><span class="keyword">let</span> dog <span class="operator">=</span> <span class="type">Dog</span>()</span><br><span class="line">dog <span class="keyword">as</span> <span class="type">Animal</span>  <span class="comment">//把 dog 转换为 Animal 类型，向上转型成功，编译器不会报错</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="keyword">let</span> dog: <span class="type">Animal</span> <span class="operator">=</span> <span class="type">Dog</span>()</span><br><span class="line">dog <span class="keyword">as</span> <span class="type">Dog</span> <span class="comment">//编译错误，此时的变量 dog 在编译时是 Animal 类型，只能向上转换，无法向下转换。</span></span><br></pre></td></tr></table></figure>

<h2 id="as-as"><a href="#as-as" class="headerlink" title="as! as?"></a>as! as?</h2><p>运行时检测，downcast（向下转型，转换成其子类类型）<br>只不过前者是强制解包，解包失败就崩溃<br>后者是可选类型   </p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//下面代码编译时均不会报错，因为 as! 和 as? 都是运行时检查的</span></span><br><span class="line"><span class="keyword">let</span> a: <span class="type">Animal</span> <span class="operator">=</span> <span class="type">Animal</span>()</span><br><span class="line">a <span class="keyword">as!</span> <span class="type">Dog</span></span><br><span class="line"><span class="number">1</span> <span class="keyword">as!</span> <span class="type">Dog</span></span><br><span class="line"><span class="number">1</span> <span class="keyword">as?</span> <span class="type">Dog</span></span><br></pre></td></tr></table></figure>

<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Dog</span>: <span class="title class_">Animal</span> &#123;</span><br><span class="line">    <span class="keyword">var</span> name <span class="operator">=</span> <span class="string">&quot;Spot&quot;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> dog: <span class="type">Animal</span> <span class="operator">=</span> <span class="type">Dog</span>()</span><br><span class="line"><span class="keyword">let</span> dog1 <span class="operator">=</span> dog <span class="keyword">as?</span> <span class="type">Dog</span> <span class="comment">//可选值</span></span><br><span class="line"><span class="keyword">let</span> dog2 <span class="operator">=</span> dog <span class="keyword">as!</span> <span class="type">Dog</span> <span class="comment">//强制解压</span></span><br><span class="line"></span><br><span class="line">dog1<span class="operator">?</span>.name <span class="comment">//可选调用</span></span><br><span class="line">dog2.name <span class="comment">//直接调用</span></span><br></pre></td></tr></table></figure>

<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>1、<code>as</code> 在编译时检测，<code>as!</code> <code>as?</code> 在运行时检测<br>2、<code>as</code> 可以用来指定文字表达类型以及向上转型<br>3、<code>as!</code> <code>as?</code> 用来向下转型，<code>as?</code> 转型后为可选值，<code>as!</code> 相当于在这个可选值上强制解压（可能会导致崩溃）</p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




  <nav class="pagination">
    <a class="extend prev" rel="prev" href="/"><i class="fa fa-angle-left" aria-label="Previous page"></i></a><a class="page-number" href="/">1</a><span class="page-number current">2</span><a class="page-number" href="/page/3/">3</a><span class="space">&hellip;</span><a class="page-number" href="/page/10/">10</a><a class="extend next" rel="next" href="/page/3/"><i class="fa fa-angle-right" aria-label="Next page"></i></a>
  </nav>

</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">


<div class="copyright">
  &copy; 2015 – 
  <span itemprop="copyrightYear">2022</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">vhuichen</span>
</div>
  <div class="powered-by">Powered by <a href="https://hexo.io/" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.js.org/pisces/" rel="noopener" target="_blank">NexT.Pisces</a>
  </div>

    </div>
  </footer>

  
  <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js" integrity="sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY=" crossorigin="anonymous"></script>
<script src="/js/comments.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/next-boot.js"></script>

  





  





</body>
</html>
